//-----------------------------------------------------------------------
// <copyright file="ExpectationsAcceptanceTest.cs" company="NMock2">
//
//   http://www.sourceforge.net/projects/NMock2
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
// </copyright>
// This is the easiest way to ignore StyleCop rules on this file, even if we shouldn't use this tag:
// <auto-generated />
//-----------------------------------------------------------------------
namespace NMock2.AcceptanceTests
{
    using NMock2.Internal;
    using NUnit.Framework;

    [TestFixture]
    public class ExpectationsAcceptanceTest : AcceptanceTestBase
    {
        [Test, ExpectedException(typeof(ExpectationException))]
        public void FailsTestIfMethodExpectedOnceButNotCalled()
        {
            SkipVerificationForThisTest();
            
            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));
            
            Expect.Once.On(helloWorld).Method("Hello").WithNoArguments();

            Mocks.VerifyAllExpectationsHaveBeenMet();
        }
        
        [Test]
        public void PassesTestIfMethodExpectedOnceAndCalled()
        {
            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));
            
            Expect.Once.On(helloWorld).Method("Hello").WithNoArguments();
            
            helloWorld.Hello();
        }
        
        [Test, ExpectedException(typeof(ExpectationException))]
        public void FailsTestIfMethodExpectedOnceButCalledTwice()
        {
            SkipVerificationForThisTest();
            
            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));
            
            Expect.Once.On(helloWorld).Method("Hello").WithNoArguments();

            helloWorld.Hello();
            helloWorld.Hello();
        }

        [Test]
        public void TestShouldPassIfExpectedExactlyNTimesAndCalledNTimes()
        {
            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));
            Expect.Exactly(N).On(helloWorld).Method("Hello").WithNoArguments();

            for (int i = 0; i < N; i++) helloWorld.Hello();
        }

        [Test, ExpectedException(typeof(ExpectationException))]
        public void TestShouldFailIfExpectedExactlyNTimesAndCalledMoreThanNTimes()
        {
            SkipVerificationForThisTest();

            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));
            Expect.Exactly(N).On(helloWorld).Method("Hello").WithNoArguments();

            for (int i = 0; i < N+1; i++) helloWorld.Hello();

            Mocks.VerifyAllExpectationsHaveBeenMet();
        }

        [Test, ExpectedException(typeof(ExpectationException))]
        public void TestShouldFailIfExpectedExactlyNTimesAndCalledLessThanNTimes()
        {
            SkipVerificationForThisTest();

            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));
            Expect.Exactly(N).On(helloWorld).Method("Hello").WithNoArguments();

            for (int i = 0; i < N - 1; i++) helloWorld.Hello();

            Mocks.VerifyAllExpectationsHaveBeenMet();
        }

        [Test, ExpectedException(typeof(ExpectationException))]
        public void FailsTestIfMethodExpectedAtLeastNTimesButCalledLessThanNTimes()
        {
            SkipVerificationForThisTest();

            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));

            Expect.AtLeast(N).On(helloWorld).Method("Hello").WithNoArguments();

            for (int i = 0; i < N-1; i++) helloWorld.Hello();

            Mocks.VerifyAllExpectationsHaveBeenMet();
        }
        
        [Test]
        public void PassesTestIfMethodExpectedAtLeastNTimesAndCalledNTimes()
        {
            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));

            Expect.AtLeast(N).On(helloWorld).Method("Hello").WithNoArguments();

            for (int i = 0; i < N; i++) helloWorld.Hello();
        }
        
        [Test]
        public void PassesTestIfMethodExpectedAtLeastNTimesAndCalledMoreThanNTimes()
        {
            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));

            Expect.AtLeast(N).On(helloWorld).Method("Hello").WithNoArguments();

            for (int i = 0; i < N+1; i++) helloWorld.Hello();
        }
        
        [Test]
        public void PassesTestIfMethodExpectedAtMostNTimesAndCalledLessThanNTimes()
        {
            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));

            Expect.AtMost(N).On(helloWorld).Method("Hello").WithNoArguments();

            for (int i = 0; i < N-1; i++) helloWorld.Hello();
        }
        
        [Test]
        public void PassesTestIfMethodExpectedAtMostNTimesAndCalledNTimes()
        {
            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));

            Expect.AtMost(N).On(helloWorld).Method("Hello").WithNoArguments();

            for (int i = 0; i < N; i++) helloWorld.Hello();
        }
        
        [Test, ExpectedException(typeof(ExpectationException))]
        public void FailsTestIfMethodExpectedAtMostNTimesAndCalledMoreThanNTimes()
        {
            SkipVerificationForThisTest();

            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));
            
            Expect.AtMost(N).On(helloWorld).Method("Hello").WithNoArguments();
            
            for (int i = 0; i < N+1; i++) helloWorld.Hello();
        }

        [Test, ExpectedException(typeof(ExpectationException))]
        public void FailsTestIfMethodExpectedBetweenNAndMTimesButCalledLessThanNTimes()
        {
            SkipVerificationForThisTest();

            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));
            
            Expect.Between(N,M).On(helloWorld).Method("Hello").WithNoArguments();

            for (int i = 0; i < N-1; i++) helloWorld.Hello();

            Mocks.VerifyAllExpectationsHaveBeenMet();
        }

        [Test, ExpectedException(typeof(ExpectationException))]
        public void FailsTestIfMethodExpectedBetweenNAndMTimesAndCalledMoreThanMTimes()
        {
            SkipVerificationForThisTest();

            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));
            
            Expect.Between(N,M).On(helloWorld).Method("Hello").WithNoArguments();

            for (int i = 0; i < M; i++) helloWorld.Hello();
            helloWorld.Hello();
        }

        [Test]
        public void PassesTestIfMethodExpectedBetweenNAndMTimesAndCalledBetweenNAndMTimes()
        {
            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));
            
            Expect.Between(N,M).On(helloWorld).Method("Hello").WithNoArguments();

            for (int i = 0; i < (N+M)/2; i++) helloWorld.Hello();
        }

        [Test, ExpectedException(typeof(ExpectationException))]
        public void FailsTestIfMethodNeverExpectedIsCalled()
        {
            SkipVerificationForThisTest();
            
            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));
            
            Expect.Never.On(helloWorld).Method("Hello").WithNoArguments();

            helloWorld.Hello();
        }

        [Test]
        public void PassesTestIfMethodNeverExpectedIsNeverCalled()
        {
            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));
            
            Expect.Never.On(helloWorld).Method("Hello").WithNoArguments();
        }
        
        [Test, ExpectedException(typeof(ExpectationException))]
        public void FailsTestIfMethodNeverExpectedIsActuallyCalled()
        {
            SkipVerificationForThisTest();

            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));
            
            Expect.Never.On(helloWorld).Method("Hello").WithNoArguments();
            
            helloWorld.Hello();
        }

        [Test]
        public void PassesTestIfMethodUsesDefaultExpectation()
        {
            IHelloWorld helloWorld = (IHelloWorld)Mocks.NewMock(typeof(IHelloWorld));

            Expect.On(helloWorld).Method("Hello").WithNoArguments();

            helloWorld.Hello();
        }

        [Test]
        public void MockToString()
        {
            IHelloWorld helloWorld = Mocks.NewNamedMock<IHelloWorld>("text");

            string s = helloWorld.ToString();

            Assert.AreEqual("text", s);
        }

        [Test]
        [Ignore("Feature for future release: mock hashcode.")]
        public void MockHash()
        {
            IHelloWorld helloWorld = Mocks.NewMock<IHelloWorld>();

            int i = helloWorld.GetHashCode();

            Assert.AreEqual(33650554, i);
        }
        
        #region Really boring stuff
        #region It really is boring stuff
        const int N = 2;
        const int M = 4;
        #endregion
        #endregion
    }
}
